home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / aztecnos.arc / TELNET.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-18  |  6.8 KB  |  337 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "mbuf.h"
  4. #include "socket.h"
  5. #include "telnet.h"
  6. #include "session.h"
  7. #include "proc.h"
  8. #include "tty.h"
  9.  
  10. #define    CTLZ    26
  11.  
  12. extern char Nospace[];
  13. extern char Badhost[];
  14. void tel_input();
  15. static void doopt(),dontopt(),willopt(),wontopt(),answer();
  16. void answer();
  17.  
  18. int Refuse_echo = 0;
  19. int Unix_line_mode = 0;    /* if true turn <cr> to <nl> when in line mode */
  20.  
  21. #ifdef    DEBUG
  22. char *T_options[] = {
  23.     "Transmit Binary",
  24.     "Echo",
  25.     "",
  26.     "Suppress Go Ahead",
  27.     "",
  28.     "Status",
  29.     "Timing Mark"
  30. };
  31. #endif
  32.  
  33. /* Execute user telnet command */
  34. int
  35. dotelnet(argc,argv)
  36. int argc;
  37. char *argv[];
  38. {
  39.     struct session *sp;
  40.     struct telnet tn;
  41.     struct sockaddr_in fsocket;
  42.     struct mbuf *bp;
  43.     char *cp;
  44.  
  45.     /* Allocate a session descriptor */
  46.     if((sp = newsession(argv[1],TELNET)) == NULLSESSION){
  47.         printf("Too many sessions\n");
  48.         return 1;
  49.     }
  50.     /* Initialize Telnet protocol descriptor */
  51.     memset((char *)&tn,0,sizeof(tn));
  52.     tn.output = Curproc;
  53.     tn.session = sp;    /* Upward pointer */
  54.     sp->cb.telnet = &tn;    /* Downward pointer */
  55.  
  56.     fsocket.sin_family = AF_INET;
  57.     if(argc < 3)
  58.         fsocket.sin_port = IPPORT_TELNET;
  59.     else
  60.         fsocket.sin_port = atoi(argv[2]);
  61.  
  62.     if((fsocket.sin_addr.s_addr = resolve(sp->name)) == 0){
  63.         printf(Badhost,sp->name);
  64.         freesession(sp);
  65.         return 1;
  66.     }
  67.     sp->s = socket(AF_INET,SOCK_STREAM,0);
  68.     printf("Trying %s...\n",psocket((struct sockaddr *)&fsocket));
  69.     if(connect(sp->s,(char *)&fsocket,SOCKSIZE) == -1){
  70.         cp = sockerr(sp->s);
  71.         printf("Telnet session %u connect failed: %s\n",
  72.          (unsigned)(sp-Sessions),cp != NULLCHAR ? cp : "");
  73.         freesession(sp);
  74.         return 1;
  75.     }
  76.     printf("Telnet session %u connected to %s\n",
  77.         (unsigned)(sp-Sessions),sp->name);
  78.     /* Fork off the receiver process */
  79.     tn.input = newproc("tel_in",512,tel_input,0,&tn);
  80.  
  81.     /* Now send whatever's typed on the terminal */
  82.     for(;;){
  83.         while(sp->input == NULLBUF)
  84.             if(pwait(&sp->input) == -1)
  85.                 goto quit;
  86.  
  87.         bp = dequeue(&sp->input);
  88.  
  89.         /* If we're doing our own echoing and recording is enabled,
  90.          * record it
  91.          */
  92.         if(!tn.remote[TN_ECHO] && sp->record != NULLFILE)
  93.             write_p(sp->record,bp);
  94.         if(send_mbuf(sp->s,bp,0,NULLCHAR,0) == -1)
  95.             break;
  96.     }
  97. quit:    close_s(sp->s);
  98.     killproc(tn.input);
  99.     freesession(sp);
  100.     return 0;
  101. }
  102.  
  103. /* User telnet receive task, started by user telnet command */
  104. void
  105. tel_input(unused,tn)
  106. int unused;
  107. struct telnet *tn;
  108. {
  109.     int c;
  110.     FILE *record;
  111.     struct session *sp;
  112.     char *cp;
  113.     struct mbuf *bp = NULLBUF;
  114.  
  115.     sp = tn->session;
  116.  
  117.     while((c = recvchar(sp->s,&bp)) != -1){
  118.  
  119.         /* Suspend output if we're not current */
  120.         while(Current != sp)
  121.             if(pwait(sp) == -1)
  122.                 goto quit;
  123.  
  124.         if(uchar(c) == IAC){
  125.             /* IAC received, get command sequence */
  126.             c = recvchar(sp->s,&bp);
  127.             switch(uchar(c)){
  128.             case WILL:
  129.                 willopt(tn,recvchar(sp->s,&bp));
  130.                 break;
  131.             case WONT:
  132.                 wontopt(tn,recvchar(sp->s,&bp));
  133.                 break;
  134.             case DO:
  135.                 doopt(tn,recvchar(sp->s,&bp));
  136.                 break;
  137.             case DONT:
  138.                 dontopt(tn,recvchar(sp->s,&bp));
  139.                 break;
  140.             case IAC:    /* Escaped IAC */
  141.                 putchar(IAC);
  142.                 if((record = sp->record) != NULLFILE)
  143.                     putc(IAC,record);
  144.                 break;
  145.             }
  146.         } else {
  147.             /* Ordinary character */
  148.             if(!tn->remote[TN_TRANSMIT_BINARY])
  149.                 c &= 0x7f;
  150.  
  151.             putchar(c);
  152.             if((record = sp->record) != NULLFILE)
  153.                 putc(c,record);
  154.         }
  155.     }
  156. quit:    /* Close seen from remote host */
  157.     free_p(bp);
  158.     cp = sockerr(sp->s);
  159.     printf("Telnet session %u closed: %s\n", (unsigned)(sp - Sessions),
  160.      cp != NULLCHAR ? cp : "EOF");
  161.     close_s(sp->s);
  162.     killproc(tn->output);
  163.     freesession(sp);
  164. }
  165.  
  166. /* File uploading task */
  167. void
  168. tel_upload(unused,sp)
  169. int unused;
  170. struct session *sp;
  171. {
  172.     struct telnet *tn;
  173.     struct mbuf *bp;
  174.  
  175.     tn = sp->cb.telnet;
  176.     for(;;){
  177.         bp = alloc_mbuf(BUFSIZ);
  178.         bp->cnt = fread(bp->data,1,BUFSIZ,sp->upload);
  179.         if(bp->cnt != 0){
  180.             send_mbuf(sp->s,bp,0,NULLCHAR,0);
  181.         } else {
  182.             free_p(bp);
  183.             break;
  184.         }
  185.     }
  186.     fclose(sp->upload);
  187.     sp->upload = NULLFILE;
  188.     free(sp->ufile);
  189.     sp->ufile = NULLCHAR;
  190.     tn->upload = NULLPROC;
  191. }
  192. /* The guts of the actual Telnet protocol: negotiating options */
  193. static
  194. void
  195. willopt(tn,opt)
  196. struct telnet *tn;
  197. char opt;
  198. {
  199.     int ack;
  200.  
  201. #ifdef    DEBUG
  202.     printf("recv: will ");
  203.     if(uchar(opt) <= NOPTIONS)
  204.         printf("%s\n",T_options[opt]);
  205.     else
  206.         printf("%u\n",opt);
  207. #endif
  208.     
  209.     switch(uchar(opt)){
  210.     case TN_TRANSMIT_BINARY:
  211.     case TN_ECHO:
  212.     case TN_SUPPRESS_GA:
  213.         if(tn->remote[uchar(opt)] == 1)
  214.             return;        /* Already set, ignore to prevent loop */
  215.         if(uchar(opt) == TN_ECHO){
  216.             if(Refuse_echo){
  217.                 /* User doesn't want to accept */
  218.                 ack = DONT;
  219.                 break;
  220.             } else
  221.                 ttysetmode(0);        /* Put tty into raw mode */
  222.         }
  223.         tn->remote[uchar(opt)] = 1;
  224.         ack = DO;            
  225.         break;
  226.     default:
  227.         ack = DONT;    /* We don't know what he's offering; refuse */
  228.     }
  229.     answer(tn,ack,opt);
  230. }
  231. static
  232. void
  233. wontopt(tn,opt)
  234. struct telnet *tn;
  235. char opt;
  236. {
  237. #ifdef    DEBUG
  238.     printf("recv: wont ");
  239.     if(uchar(opt) <= NOPTIONS)
  240.         printf("%s\n",T_options[uchar(opt)]);
  241.     else
  242.         printf("%u\n",uchar(opt));
  243. #endif
  244.     if(uchar(opt) <= NOPTIONS){
  245.         if(tn->remote[uchar(opt)] == 0)
  246.             return;        /* Already clear, ignore to prevent loop */
  247.         tn->remote[uchar(opt)] = 0;
  248.         if(uchar(opt) == TN_ECHO)
  249.             ttysetmode(TTY_ECHO|TTY_EDIT);    /* Put tty into cooked mode */
  250.     }
  251.     answer(tn,DONT,opt);    /* Must always accept */
  252. }
  253. static
  254. void
  255. doopt(tn,opt)
  256. struct telnet *tn;
  257. char opt;
  258. {
  259.     int ack;
  260.  
  261. #ifdef    DEBUG
  262.     printf("recv: do ");
  263.     if(uchar(opt) <= NOPTIONS)
  264.         printf("%s\n",T_options[uchar(opt)]);
  265.     else
  266.         printf("%u\n",uchar(opt));
  267. #endif
  268.     switch(uchar(opt)){
  269. #ifdef    FUTURE    /* Use when local options are implemented */
  270.         if(tn->local[uchar(opt)] == 1)
  271.             return;        /* Already set, ignore to prevent loop */
  272.         tn->local[uchar(opt)] = 1;
  273.         ack = WILL;
  274.         break;
  275. #endif
  276.     default:
  277.         ack = WONT;    /* Don't know what it is */
  278.     }
  279.     answer(tn,ack,opt);
  280. }
  281. static
  282. void
  283. dontopt(tn,opt)
  284. struct telnet *tn;
  285. char opt;
  286. {
  287. #ifdef    DEBUG
  288.     printf("recv: dont ");
  289.     if(uchar(opt) <= NOPTIONS)
  290.         printf("%s\n",T_options[uchar(opt)]);
  291.     else
  292.         printf("%u\n",uchar(opt));
  293. #endif
  294.     if(uchar(opt) <= NOPTIONS){
  295.         if(tn->local[uchar(opt)] == 0){
  296.             /* Already clear, ignore to prevent loop */
  297.             return;
  298.         }
  299.         tn->local[uchar(opt)] = 0;
  300.     }
  301.     answer(tn,WONT,opt);
  302. }
  303. static
  304. void
  305. answer(tn,r1,r2)
  306. struct telnet *tn;
  307. int r1,r2;
  308. {
  309.     char s[3];
  310.  
  311. #ifdef    DEBUG
  312.     switch(r1){
  313.     case WILL:
  314.         printf("sent: will ");
  315.         break;
  316.     case WONT:
  317.         printf("sent: wont ");
  318.         break;
  319.     case DO:
  320.         printf("sent: do ");
  321.         break;
  322.     case DONT:
  323.         printf("sent: dont ");
  324.         break;
  325.     }
  326.     if(r2 <= 6)
  327.         printf("%s\n",T_options[r2]);
  328.     else
  329.         printf("%u\n",r2);
  330. #endif
  331.  
  332.     s[0] = IAC;
  333.     s[1] = r1;
  334.     s[2] = r2;
  335.     send(tn->session->s,s,3,0);
  336. }
  337.